//Partial   所有属性 可选的意思
//Required  所有属性 必选的意思
//Pick      提取部分属性
//Exclude   排除部分属性
//Omit      排除部分属性 并且返回新的类型

import { type } from "os"


//Partial   所有属性 可选的意思
interface genericsUser01 {
  name: string
  age: number
  address: string
}

type userPartial = Partial<genericsUser01>

// 原理
/* 
type CustomPartial<T> = {
  [p in keyof T]: T[p]
}

type userPartial = CustomPartial<genericsUser01>
*/

// 效果
/* 
type userPartial = {
    name?: string | undefined;
    age?: number | undefined;
    address?: string | undefined;
}
*/


//Required  所有属性 必选的意思
interface genericsUser02 {
  name?: string
  age?: number
  address?: string
}

type userRequired = Required<genericsUser02>

// 原理
/* 
type CustomPartialRequired<T> = {
  [P in keyof T]-?: T[P]
}

type userRequired = CustomPartialRequired<genericsUser02>
*/

// 效果
/* 
type userRequired = {
  name: string;
  age: number;
  address: string;
}
*/

//Pick      提取部分属性
interface genericsUser03 {
  name: string
  age: number
  address: string
  sex: string
}

type userPick = Pick<genericsUser03, 'name' | 'age'>
// 原理
/* 
每次判断K是否是T的子类型  是的话就留着
type CustomPick<T, K extends keyof T> = {
  [P in K]: T[P]
}

type userPick = CustomPick<genericsUser03, 'name' | 'age'>
*/

// 效果
/* 
type userPick = {
    name: string;
    age: number;
}
*/

//Exclude   排除部分属性
interface genericsUser04 {
  name: string
  age: number
  address: string
  sex: string
}

type userExclude = Exclude<keyof genericsUser04, 'name' | 'age'>  //  keyof genericsUser04 等价于 'name' | 'age' | 'address' | 'sex'
// 原理
/* 
每次判断T是否是K的子类型   不是的话就留着
type CustomExclude<T, K> = T extends K ? never : T
type userExclude = CustomExclude<keyof genericsUser04, 'name' | 'age'>

深度解析
为什么是never
never会在联合类型中被过滤掉

type = name | age | address | sex | never
type = never | never | address | sex | never
*/

// 效果
/* 
type userExclude = "address" | "sex";
*/


// Omit      排除部分属性 并且返回新的类型
interface genericsUser05 {
  name: string
  age: number
  address: string
  sex: string
}

// 武魂融合技 Exclude + Pick
// Exclude 去排除不需要的属性
// Pick 去选择需要的属性

type CustomOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type userOmit = CustomOmit<genericsUser05, 'age'>